from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
import json
import time
import os
import sys
import datetime
import random
import requests
import re

class WeiboAutoReposter:
    def __init__(self):

        self.driver = self._init_driver()
        self.target_user = "大皖新闻"  # 目标用户名

        self.api_url = "https://api.siliconflow.cn/v1/chat/completions"
        self.api_key = "sk-nbnpftafdbxqfttaedidmqpwevinkvixnucpudanuykywflx"
        self.max_retries = 3
        # 从文件加载历史记录
        self.processed_mids = set()
        if os.path.exists("processed.log"):
            with open("processed.log", "r") as f:
                self.processed_mids = set(f.read().splitlines())

        # 凌晨减少检查频率
        hour = datetime.datetime.now().hour
        if 0 <= hour < 7:  
            self.check_interval = (25200,25400)  # 7小时
        else:
            self.check_interval = (360, 600)
        self.last_mid = None  # 最后转发的微博ID
        self.cookie_file = "weibo_cookies.json"

        # 初始化cookies
        if os.path.exists(self.cookie_file):
            self.login_with_cookies()
        else:
            self.manual_login()
            self.save_cookies()
    
    def _safe_extract(self, response_data):
        """安全提取生成内容"""
        try:
            return response_data["choices"][0]["message"]["content"].strip()
        except (KeyError, IndexError) as e:
            raise ValueError(f"响应解析失败: {str(e)}")
        
    def generate(self, weibo_content):
        """执行评论生成"""
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        for attempt in range(self.max_retries):
            try:
                response = requests.post(
                    self.api_url,
                    json=self._generate_payload(weibo_content),
                    headers=headers,
                    timeout=60
                )
                print(response.text)
                response.raise_for_status()
                return self._safe_extract(response.json())
                
            except requests.exceptions.RequestException as e:
                if attempt == self.max_retries - 1:
                    raise Exception(f"API请求失败: {str(e)}")
                time.sleep(2 ** attempt)
                
        return None

    def _generate_payload(self, weibo_content):
        """构造API请求参数"""
        return {
            "model": "Qwen/Qwen2.5-72B-Instruct",
            "stream": False,
            "max_tokens": 512,
            "temperature": 0.7,
            "top_p": 0.7,
            "top_k": 50,
            "frequency_penalty": 0.5,
            "n": 1,
            "messages": [{
                "role": "user",
                "content": f"对下面新浪微博内容生成小于5字的评论：{weibo_content}"
            }],
        }

    # 配置浏览器选项
    def _init_driver(self):
     
        current_dir = os.path.dirname(os.path.abspath(__file__))
        options = Options()
        options.add_argument('--no-sandbox')  # 禁用沙箱
        options.add_argument('--disable-dev-shm-usage')  # 禁用共享内存
        options.add_argument('--force-device-scale-factor=1')
        chrome_dir = os.path.join(current_dir, "chrome")
        options.binary_location =os.path.join(chrome_dir, "chrome.exe")
        driver_path = os.path.join(current_dir, "drivers", "chromedriver.exe")
        service = Service(executable_path=driver_path)
        driver = webdriver.Chrome(service=service, options=options)
        return driver

    def get_topic(text: str) -> str:
        """
        精准提取文本中第一个完整的话题标签
        参数：
            text (str): 需要解析的文本内容
        返回：
            str: 提取到的第一个话题内容（不带#号），若无合法话题返回空字符串
        """
        pattern = r'(?<!\\)#((?:[^#\\]|\\.)+?)#'

        match = re.search(pattern, text, flags=re.DOTALL)
        return match.group(0) if match else ''
    
    def save_cookies(self):
        with open(self.cookie_file, 'w') as f:
            json.dump(self.driver.get_cookies(), f)

    def load_cookies(self):
        self.driver.get("https://weibo.com")
        with open(self.cookie_file, 'r') as f:
            cookies = json.load(f)
            for cookie in cookies:
                self.driver.add_cookie(cookie)
        self.driver.refresh()

    def manual_login(self):
        self.driver.get("https://weibo.com/login.php")
        input("请手动完成登录后按回车继续...")

    def login_with_cookies(self):
        try:
            self.load_cookies()
            # 验证登录是否成功
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CLASS_NAME, "gn_name"))
            )
            print("登录成功")
        except Exception as e:
            print("Cookie登录失败，请手动登录")
            self.manual_login()
            self.save_cookies()

    def get_target_weibo(self):
        # 跳转到目标用户主页
        self.driver.get(f"https://weibo.com/n/{self.target_user}")
        scroll_count = 3
        weibo_list =  []
        
        try:               
            # 等待主容器加载
            WebDriverWait(self.driver, 15).until(
                EC.presence_of_element_located((By.XPATH, '//div[@class="container"]//div[contains(@class,"wbpro-scroller-item") and @data-index]'))
            )
            for i in range(1, scroll_count + 1):
                # 计算动态滚动距离（屏幕高度的80%）
                window_height = self.driver.execute_script("return window.innerHeight")
                scroll_distance = int(window_height * 0.8 * i)  # 滚动距离递增
                
                # 执行可控滚动
                self.driver.execute_script(
                    f"window.scrollTo({{top: {scroll_distance}, behavior: 'smooth'}});"
                )
                
                # 等待主容器加载
                WebDriverWait(self.driver, 15).until(
                    EC.presence_of_element_located((By.XPATH, '//div[@class="container"]//div[contains(@class,"wbpro-scroller-item") and @data-index]'))
                )

                # 短等待模拟人类浏览
                time.sleep(random.uniform(1.5, 2.8))
            # 精准定位
            weibo_list = self.driver.find_elements(By.XPATH, '//div[@class="container"]//div[contains(@class,"wbpro-scroller-item") and @data-index]')
            print(f"成功获取到 {len(weibo_list)} 条微博")
            return weibo_list
        
        except Exception as e:
            print("元素定位失败:", str(e))
            return []


    def repost_weibo(self, weibo_item):
        try:
            # 定位评论按钮
            repost_btn = weibo_item.find_element(By.XPATH, './/i[@title="评论"]')
            
            # 滚动到元素可见（核心修正）
            self.driver.execute_script(
                "arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});"
                "window.scrollBy(0, -50);", 
                repost_btn
            )

            # 生成智能评论
            content_element = weibo_item.find_element(By.XPATH, './/div[@class="wbpro-feed-content"]')
            print(content_element.text)
            comment_text = self.generate(content_element.text)
            print("生成评论内容:", comment_text)
            #comment_text = self.get_topic(content_element.text)    
            if not comment_text or len(comment_text) > 5 or len(comment_text) < 2:
                raise ValueError("生成内容不符合要求")
            
            # 显式等待元素可点击
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.XPATH, './/i[@title="评论"]'))
            )
            
            # 使用ActionChains模拟人类操作
            ActionChains(self.driver).move_to_element(repost_btn).pause(3.4).click().perform()
            print("点击评论按钮")

            WebDriverWait(self.driver, 15).until(
                EC.presence_of_element_located((By.XPATH, '//textarea[@placeholder="发布你的评论"]'))
            )            
            # 输入转发内容
            time.sleep(1)
            text_area = self.driver.find_element(By.XPATH, '//textarea[@placeholder="发布你的评论"]')
            text_area.send_keys(comment_text)
            print("输入评论内容") 

            # 勾选转发
            time.sleep(1)
            re_btn = self.driver.find_element(By.XPATH, './/span[@class="woo-checkbox-shadow"]')
            ActionChains(self.driver).move_to_element(re_btn).pause(3.2).click().perform()
            print("勾选同时转发")
            
            # 使用ActionChains模拟人类操作
            comfpost_btn = self.driver.find_element(By.XPATH, '//button[.//span[text()="评论"]]')
            ActionChains(self.driver).move_to_element(comfpost_btn).pause(2.1).click().perform()
       
            print("评论转发成功")

            # 点赞
            time.sleep(2)
            weibo_item.find_element(By.XPATH, './/button[@title="赞"]').click()
            print("点赞成功")

            return True
        except Exception as e:
            print("评论转发失败:", str(e))
            return False
    def run(self):
        try:
            while True:
                print("开始检查新微博...")
                weibo_list = self.get_target_weibo()
                
                if weibo_list:
                    # 逆序处理：从旧到新，避免重复处理最新微博
                    for weibo in reversed(weibo_list):
                        try:
                            # 更健壮的MID提取方式
                            weibo_link = weibo.find_element(By.XPATH, './/a[contains(@href, "weibo.com/")]')
                            href = weibo_link.get_attribute("href")
                            current_mid = href.split("/")[-1].split("?")[0]  # 处理带参数的URL
                        except Exception as e:
                            print(f"提取MID失败: {str(e)}")
                            continue  # 跳过无法处理的微博

                        if current_mid not in self.processed_mids:
                            print(f"发现未评论转发的新微博 {current_mid}")
                            if self.repost_weibo(weibo):
                                self.processed_mids.add(current_mid)
                                print(f"{datetime.datetime.now()}成功记录已转发ID: {current_mid}")
                                # 可选：写入日志文件
                                with open("processed.log", "a") as f:
                                    f.write(f"{current_mid}\n")
                                time.sleep(90)
                            else:
                                print(f"跳过评论转发失败的微博: {current_mid}")
                        else:
                            print(f"微博ID: {current_mid}已处理...")
                else:
                    print("没有检测到新的微博")

                wait_time=random.randint(*self.check_interval)
                print(f"等待{wait_time}秒后再次检查...")
                time.sleep(wait_time)
                
        finally:
            self.driver.quit()

if __name__ == "__main__":
    bot = WeiboAutoReposter()
    bot.run()
